home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Very Best of Atari Inside
/
The Very Best of Atari Inside 1.iso
/
mint
/
mint110s
/
util.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-09-14
|
13KB
|
654 lines
/*
Copyright 1990,1991,1992 Eric R. Smith.
Copyright 1992,1993 Atari Corporation.
All rights reserved.
*/
/*
* misc. utility routines
*/
#include "mint.h"
/*
* given an address, find the corresponding memory region in this program's
* memory map
*/
MEMREGION *
addr2mem(a)
virtaddr a;
{
int i;
for (i = 0; i < curproc->num_reg; i++) {
if (a == curproc->addr[i])
return curproc->mem[i];
}
return 0;
}
/*
* given a pid, return the corresponding process
*/
PROC *
pid2proc(pid)
int pid;
{
PROC *p;
for (p = proclist; p; p = p->gl_next) {
if (p->pid == pid)
return p;
}
return 0;
}
/*
* return a new pid
*/
int
newpid()
{
static int _maxpid = 1;
int i;
#ifndef NDEBUG
int j = 0;
#endif
do {
i = _maxpid++;
if (_maxpid >= 1000) _maxpid = 1;
assert(j++ < 1000);
} while (pid2proc(i));
return i;
}
/*
* zero out a block of memory, quickly; the block must be word-aligned,
* and should be long-aligned for speed reasons
*/
void
zero(place, size)
char *place;
long size;
{
long cruft;
long blocksize;
cruft = size % 256; /* quickzero does 256 byte blocks */
blocksize = size/256; /* divide by 256 */
if (blocksize > 0) {
quickzero(place, blocksize);
place += (blocksize*256);
}
while (cruft > 0) {
*place++ = 0;
cruft--;
}
}
#ifdef JUNK_MEM
void
fillwjunk(place, size)
long *place;
long size;
{
while (size > 0) {
*place++ = size;
size -= 4;
}
}
#endif
/*
* kernel memory allocation routines
*/
#define KERMEM_THRESHOLD (QUANTUM-8)
#if 0
#define KERMEM_SIZE QUANTUM
#else
#define KERMEM_SIZE ((KERMEM_THRESHOLD+8)*2)
#endif
#define KMAGIC ((MEMREGION *)0x87654321L)
#define NKMAGIC 0x19870425L
void * ARGS_ON_STACK
kmalloc(size)
long size;
{
MEMREGION *m;
MEMREGION **p;
long *lp;
/*
* increase size by two pointers' worth: the first contains
* a pointer to the region descriptor for this block, and the
* second contains KMAGIC. If the block came from nalloc,
* then they both contain NKMAGIC.
*/
size += sizeof(m) + sizeof(m);
/*
* for small requests, we use nalloc first
*/
tryagain:
if (size < KERMEM_THRESHOLD) {
lp = nalloc(size);
if (lp) {
*lp++ = NKMAGIC;
*lp++ = NKMAGIC;
TRACELOW(("kmalloc(%lx) -> (nalloc) %lx",size,lp));
return lp;
}
else {
DEBUG(("kmalloc(%lx): nalloc is out of memory",size));
/* If this is commented out, then we fall through to try_getregion */
if (0 == (m = get_region(alt, KERMEM_SIZE, PROT_S))) {
if (0 == (m = get_region(core, KERMEM_SIZE, PROT_S))) {
DEBUG(("No memory for another arena"));
goto try_getregion;
}
}
lp = (long *)m->loc;
*lp++ = (long)KMAGIC;
*lp++ = (long)m;
#if 0
nalloc_arena_add((void *)lp,KERMEM_SIZE - 2*SIZEOF(long));
#else
nalloc_arena_add((void *)lp,KERMEM_SIZE);
#endif
goto tryagain;
}
}
try_getregion:
m = get_region(alt, size, PROT_S);
if (!m) m = get_region(core, size, PROT_S);
if (m) {
p = (MEMREGION **)m->loc;
*p++ = KMAGIC;
*p++ = m;
TRACELOW(("kmalloc(%lx) -> (get_region) %lx",size,p));
return (void *)p;
}
else {
TRACELOW(("kmalloc(%lx) -> (fail)",size));
#if 0
/* this is a serious offense; I want to hear about it */
/* maybe Allan wanted to hear about it, but ordinary users
* won't! -- ERS
*/
NALLOC_DUMP();
BIG_MEM_DUMP(0,0);
#endif
return 0;
}
}
/* allocate from ST memory only */
void *
kcore(size)
long size;
{
MEMREGION *m;
MEMREGION **p;
size += sizeof(m) + sizeof (m);
m = get_region(core, size, PROT_S);
if (m) {
p = (MEMREGION **)m->loc;
*p++ = KMAGIC;
*p++ = m;
return (void *)p;
}
else {
return 0;
}
}
void ARGS_ON_STACK
kfree(place)
void *place;
{
MEMREGION **p;
MEMREGION *m;
TRACELOW(("kfree(%lx)",place));
if (!place) return;
p = place;
p -= 2;
if (*p == (MEMREGION *)NKMAGIC) {
nfree(p);
return;
}
else if (*p++ != KMAGIC) {
FATAL("kfree: memory not allocated by kmalloc");
}
m = *p;
if (--m->links != 0) {
FATAL("kfree: block has %d links", m->links);
}
free_region(m);
}
/*
* "user" memory allocation routines; the kernel can use these to
* allocate/free memory that will be attached in some way to a process
* (and freed automatically when the process exits)
*/
void * ARGS_ON_STACK
umalloc(size)
long size;
{
return (void *)m_xalloc(size, 3);
}
void ARGS_ON_STACK
ufree(block)
void *block;
{
(void)m_free((virtaddr)block);
}
/*
* convert a time in milliseconds to a GEMDOS style date/time
* timeptr[0] gets the time, timeptr[1] the date.
* BUG/FEATURE: in the conversion, it is assumed that all months have
* 30 days and all years have 360 days.
*/
void ARGS_ON_STACK
ms_time(ms, timeptr)
ulong ms;
short *timeptr;
{
ulong secs;
short tsec, tmin, thour;
short tday, tmonth, tyear;
secs = ms / 1000;
tsec = secs % 60;
secs /= 60; /* secs now contains # of minutes */
tmin = secs % 60;
secs /= 60; /* secs now contains # of hours */
thour = secs % 24;
secs /= 24; /* secs now contains # of days */
tday = secs % 30;
secs /= 30;
tmonth = secs % 12;
tyear = secs / 12;
*timeptr++ = (thour << 11) | (tmin << 5) | (tsec >> 1);
*timeptr = (tyear << 9) | ((tmonth + 1) << 5) | (tday+1);
}
/*
* unixtim(time, date): convert a Dos style (time, date) pair into
* a Unix time (seconds from midnight Jan 1., 1970)
*/
static int
mth_start[13] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
long ARGS_ON_STACK
unixtim(time, date)
unsigned time, date;
{
int sec, min, hour;
int mday, mon, year;
long y, s;
sec = (time & 31) << 1;
min = (time >> 5) & 63;
hour = (time >> 11) & 31;
mday = date & 31;
mon = ((date >> 5) & 15) - 1;
year = 80 + ((date >> 9) & 255);
/* calculate tm_yday here */
y = (mday - 1) + mth_start[mon] + /* leap year correction */
( ( (year % 4) != 0 ) ? 0 : (mon > 1) );
s = (sec) + (min * 60L) + (hour * 3600L) +
(y * 86400L) + ((year - 70) * 31536000L) +
((year - 69)/4) * 86400L;
return s;
}
/* convert a Unix time into a DOS time. The longword returned contains
the time word first, then the date word.
BUG: we completely ignore any time zone information.
*/
#define SECS_PER_MIN (60L)
#define SECS_PER_HOUR (3600L)
#define SECS_PER_DAY (86400L)
#define SECS_PER_YEAR (31536000L)
#define SECS_PER_LEAPYEAR (SECS_PER_DAY + SECS_PER_YEAR)
static int
days_per_mth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
long ARGS_ON_STACK
dostim(t)
long t;
{
unsigned long time, date;
int tm_hour, tm_min, tm_sec;
int tm_year, tm_mon, tm_mday;
int i;
if (t <= 0) return 0;
tm_year = 70;
while (t >= SECS_PER_YEAR) {
if ((tm_year & 0x3) == 0) {
if (t < SECS_PER_LEAPYEAR)
break;
t -= SECS_PER_LEAPYEAR;
} else {
t -= SECS_PER_YEAR;
}
tm_year++;
}
tm_mday = (int)(t/SECS_PER_DAY);
days_per_mth[1] = (tm_year & 0x3) ? 28 : 29;
for (i = 0; tm_mday >= days_per_mth[i]; i++)
tm_mday -= days_per_mth[i];
tm_mon = i+1;
tm_mday++;
t = t % SECS_PER_DAY;
tm_hour = (int)(t/SECS_PER_HOUR);
t = t % SECS_PER_HOUR;
tm_min = (int)(t/SECS_PER_MIN);
tm_sec = (int)(t % SECS_PER_MIN);
if (tm_year < 80) {
tm_year = 80;
tm_mon = tm_mday = 1;
tm_hour = tm_min = tm_sec = 0;
}
time = (tm_hour << 11) | (tm_min << 5) | (tm_sec >> 1);
date = ((tm_year - 80) & 0x7f) << 9;
date |= ((tm_mon) << 5) | (tm_mday);
return (time << 16) | date;
}
/*
* Case insensitive string comparison. note that this only returns
* 0 (match) or nonzero (no match), and that the returned value
* is not a reliable indicator of any "order".
*/
int ARGS_ON_STACK
strnicmp(str1, str2, len)
register const char *str1, *str2;
register int len;
{
register char c1, c2;
do {
c1 = *str1++; if (isupper(c1)) c1 = tolower(c1);
c2 = *str2++; if (isupper(c2)) c2 = tolower(c2);
} while (--len >= 0 && c1 && c1 == c2);
if (len < 0 || c1 == c2)
return 0;
return c1 - c2;
}
int ARGS_ON_STACK
stricmp(str1, str2)
const char *str1, *str2;
{
return strnicmp(str1, str2, 0x7fff);
}
/*
* string utilities: strlwr() converts a string to lower case, strupr()
* converts it to upper case
*/
char * ARGS_ON_STACK
strlwr(s)
char *s;
{
char c;
char *old = s;
while ((c = *s) != 0) {
if (isupper(c)) {
*s = _tolower(c);
}
s++;
}
return old;
}
char * ARGS_ON_STACK
strupr(s)
char *s;
{
char c;
char *old = s;
while ((c = *s) != 0) {
if (islower(c)) {
*s = _toupper(c);
}
s++;
}
return old;
}
#ifdef OWN_LIB
/*
* Case sensitive comparison functions.
*/
int
strncmp(str1, str2, len)
register const char *str1, *str2;
register int len;
{
register char c1, c2;
do {
c1 = *str1++;
c2 = *str2++;
} while (--len >= 0 && c1 && c1 == c2);
if (len < 0) return 0;
return c1 - c2;
}
int
strcmp(str1, str2)
const char *str1, *str2;
{
register char c1, c2;
do {
c1 = *str1++;
c2 = *str2++;
} while (c1 && c1 == c2);
return c1 - c2;
}
/*
* some standard string functions
*/
char *
strcat(dst, src)
char *dst;
const char *src;
{
register char *_dscan;
for (_dscan = dst; *_dscan; _dscan++) ;
while ((*_dscan++ = *src++) != 0) ;
return dst;
}
char *
strcpy(dst, src)
char *dst;
const char *src;
{
register char *_dscan = dst;
while ((*_dscan++ = *src++) != 0) ;
return dst;
}
char *
strncpy(dst, src, len)
char *dst;
const char *src;
int len;
{
register char *_dscan = dst;
while (--len >= 0 && (*_dscan++ = *src++) != 0)
continue;
while (--len >= 0)
*_dscan++ = 0;
return dst;
}
int
strlen(scan)
const char *scan;
{
register const char *_start = scan+1;
while (*scan++) ;
return (int)((long)scan - (long)_start);
}
/*
* strrchr: find the last occurence of a character in a string
*/
char *
strrchr(str, which)
const char *str;
register int which;
{
register unsigned char c, *s;
register char *place;
s = (unsigned char *)str;
place = 0;
do {
c = *s++;
if (c == which)
place = (char *)s-1;
} while (c);
return place;
}
unsigned char _ctype[256] =
{
_CTc, _CTc, _CTc, _CTc, /* 0x00..0x03 */
_CTc, _CTc, _CTc, _CTc, /* 0x04..0x07 */
_CTc, _CTc|_CTs, _CTc|_CTs, _CTc|_CTs, /* 0x08..0x0B */
_CTc|_CTs, _CTc|_CTs, _CTc, _CTc, /* 0x0C..0x0F */
_CTc, _CTc, _CTc, _CTc, /* 0x10..0x13 */
_CTc, _CTc, _CTc, _CTc, /* 0x14..0x17 */
_CTc, _CTc, _CTc, _CTc, /* 0x18..0x1B */
_CTc, _CTc, _CTc, _CTc, /* 0x1C..0x1F */
_CTs, _CTp, _CTp, _CTp, /* 0x20..0x23 */
_CTp, _CTp, _CTp, _CTp, /* 0x24..0x27 */
_CTp, _CTp, _CTp, _CTp, /* 0x28..0x2B */
_CTp, _CTp, _CTp, _CTp, /* 0x2C..0x2F */
_CTd|_CTx, _CTd|_CTx, _CTd|_CTx, _CTd|_CTx, /* 0x30..0x33 */
_CTd|_CTx, _CTd|_CTx, _CTd|_CTx, _CTd|_CTx, /* 0x34..0x37 */
_CTd|_CTx, _CTd|_CTx, _CTp, _CTp, /* 0x38..0x3B */
_CTp, _CTp, _CTp, _CTp, /* 0x3C..0x3F */
_CTp, _CTu|_CTx, _CTu|_CTx, _CTu|_CTx, /* 0x40..0x43 */
_CTu|_CTx, _CTu|_CTx, _CTu|_CTx, _CTu, /* 0x44..0x47 */
_CTu, _CTu, _CTu, _CTu, /* 0x48..0x4B */
_CTu, _CTu, _CTu, _CTu, /* 0x4C..0x4F */
_CTu, _CTu, _CTu, _CTu, /* 0x50..0x53 */
_CTu, _CTu, _CTu, _CTu, /* 0x54..0x57 */
_CTu, _CTu, _CTu, _CTp, /* 0x58..0x5B */
_CTp, _CTp, _CTp, _CTp, /* 0x5C..0x5F */
_CTp, _CTl|_CTx, _CTl|_CTx, _CTl|_CTx, /* 0x60..0x63 */
_CTl|_CTx, _CTl|_CTx, _CTl|_CTx, _CTl, /* 0x64..0x67 */
_CTl, _CTl, _CTl, _CTl, /* 0x68..0x6B */
_CTl, _CTl, _CTl, _CTl, /* 0x6C..0x6F */
_CTl, _CTl, _CTl, _CTl, /* 0x70..0x73 */
_CTl, _CTl, _CTl, _CTl, /* 0x74..0x77 */
_CTl, _CTl, _CTl, _CTp, /* 0x78..0x7B */
_CTp, _CTp, _CTp, _CTc, /* 0x7C..0x7F */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x80..0x8F */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x90..0x9F */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xA0..0xAF */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xB0..0xBF */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xC0..0xCF */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xD0..0xDF */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xE0..0xEF */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 0xF0..0xFF */
};
int toupper(c)
int c;
{
return(islower(c) ? (c ^ 0x20) : (c));
}
int tolower(c)
int c;
{
return(isupper(c) ? (c ^ 0x20) : (c));
}
/*
* converts a decimal string to an integer
*/
long
atol(s)
const char *s;
{
long d = 0;
int negflag = 0;
int c;
while (*s && isspace(*s)) s++;
while (*s == '-' || *s == '+') {
if (*s == '-')
negflag ^= 1;
s++;
}
while ((c = *s++) != 0 && isdigit(c)) {
d = 10 * d + (c - '0');
}
if (negflag) d = -d;
return d;
}
#endif /* OWN_LIB */